package com.yunkeji.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunkeji.common.core.domain.PageQuery;
import com.yunkeji.common.core.domain.dto.PayLogDTO;
import com.yunkeji.common.core.domain.event.PushRollingEvent;
import com.yunkeji.common.core.page.TableDataInfo;
import com.yunkeji.common.enums.app.PayLogTypeEnums;
import com.yunkeji.common.enums.app.PayStatusEnum;
import com.yunkeji.common.enums.app.PayTypeEnum;
import com.yunkeji.common.exception.ServiceException;
import com.yunkeji.common.helper.LoginHelper;
import com.yunkeji.common.msg.PushMessage;
import com.yunkeji.common.utils.StringUtils;
import com.yunkeji.dao.domain.*;
import com.yunkeji.dao.mapper.*;
import com.yunkeji.dao.vo.MonthStatisticsVo;
import com.yunkeji.dao.vo.PayDetailVo;
import com.yunkeji.dao.vo.StatisticsVo;
import com.yunkeji.dao.vo.broker.InviteInfoVo;
import com.yunkeji.system.domain.bo.*;
import com.yunkeji.system.service.IBrokerUserService;
import com.yunkeji.system.service.IInviteRewardService;
import com.yunkeji.system.service.IPayDetailService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 充值明细Service业务层处理
 *
 * @author zhang
 * @date 2024-07-10
 */
@RequiredArgsConstructor
@Service
public class PayDetailServiceImpl implements IPayDetailService {

    private final PayDetailMapper baseMapper;
    private final PayRechargePlanMapper planMapper;
    private final AppUserMapper userMapper;
    private final AppUserExtMapper extMapper;
    private final AppUserWalletMapper walletMapper;
    private final IInviteRewardService rewardService;

    /**
     * 查询充值明细
     */
    @Override
    public PayDetailVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询充值明细列表
     */
    @Override
    public TableDataInfo<PayDetailVo> queryPageList(PayDetailBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PayDetail> lqw = buildQueryWrapper(bo);
//        Page<PayDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        Page<PayDetailVo> result = baseMapper.selectListPage(
            bo.getPlatformId(),
            bo.getPayType(),
            bo.getOrderId(),
            bo.getThirdId(),
            bo.getRechargeType(),
            bo.getStatus(),
            bo.getPayTimeStart(),
            bo.getPayTimeEnd(),
            pageQuery.build());
        return TableDataInfo.build(result);
    }

    /**
     * 查询充值明细列表
     */
    @Override
    public List<PayDetailVo> queryList(PayDetailBo bo) {
        LambdaQueryWrapper<PayDetail> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PayDetail> buildQueryWrapper(PayDetailBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PayDetail> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, PayDetail::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderId()), PayDetail::getOrderId, bo.getOrderId());
        lqw.eq(StringUtils.isNotBlank(bo.getThirdId()), PayDetail::getThirdId, bo.getThirdId());
        lqw.eq(bo.getBranch() != null, PayDetail::getBranch, bo.getBranch());
        lqw.eq(bo.getStatus() != null, PayDetail::getStatus, bo.getStatus());
        lqw.eq(
            bo.getBeforeGoldBalance() != null,
            PayDetail::getBeforeGoldBalance,
            bo.getBeforeGoldBalance());
        lqw.eq(bo.getCnyPrice() != null, PayDetail::getCnyPrice, bo.getCnyPrice());
        lqw.eq(bo.getGold() != null, PayDetail::getGold, bo.getGold());
        lqw.eq(bo.getPayType() != null, PayDetail::getPayType, bo.getPayType());
        lqw.eq(
            bo.getAfterGoldBalance() != null,
            PayDetail::getAfterGoldBalance,
            bo.getAfterGoldBalance());
        lqw.eq(bo.getPlatformId() != null, PayDetail::getPlatformId, bo.getPlatformId());
        lqw.eq(bo.getRechargeType() != null, PayDetail::getRechargeType, bo.getRechargeType());
        lqw.eq(bo.getMonth() != null, PayDetail::getMonth, bo.getMonth());
        lqw.eq(
            bo.getAfterExpireTime() != null,
            PayDetail::getAfterExpireTime,
            bo.getAfterExpireTime());
        lqw.eq(
            bo.getBeforeExpireTime() != null,
            PayDetail::getBeforeExpireTime,
            bo.getBeforeExpireTime());
        lqw.ge(null != bo.getPayTimeStart() && null == bo.getPayTimeEnd(),
            PayDetail::getCreateTime,
            bo.getPayTimeStart());
        lqw.le(null == bo.getPayTimeStart() && null != bo.getPayTimeEnd(),
            PayDetail::getCreateTime,
            bo.getPayTimeEnd());
        lqw.between(null != bo.getPayTimeStart() && null != bo.getPayTimeEnd(),
            PayDetail::getCreateTime,
            bo.getPayTimeStart(),
            bo.getPayTimeEnd());
        lqw.orderByDesc(PayDetail::getCreateTime);
        return lqw;
    }

    /**
     * 新增充值明细
     */
    @Override
    public Boolean insertByBo(PayDetailBo bo) {
        PayDetail add = BeanUtil.toBean(bo, PayDetail.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }


    @Override
    public void manualRecharge(ManualRechargeBo bo) {
        if (Objects.isNull(bo.getGold()) || bo.getGold().doubleValue() < 1) {
            throw new ServiceException("金额不能小于1！");
        }
        AppUser user = userMapper.selectOne(Wrappers.lambdaQuery(AppUser.class).eq(AppUser::getPlatformId, bo.getPlatformId()));
        if(Objects.isNull(user)) {
            throw new ServiceException("用户未找到！");
        }
        PayDetail payDetail =
            PayDetail.builder()
                .platformId(bo.getPlatformId())
                .planSnap("{}")
                .userId(user.getId())
                .cnyPrice(bo.getCnyPrice())
                .orderId(System.currentTimeMillis() + "" + Math.floor(Math.random() * 9000 + 1000))
                .branch(user.getBranch())
                .oaid("")
                .status(PayStatusEnum.已支付.getCode())
                .gold(bo.getGold())
                .payType(PayTypeEnum.后台手动添加.getCode())
                .remark(bo.getRemark())
                .build();
        baseMapper.insert(payDetail);

        AppUserExt appUserExt = extMapper.selectById(payDetail.getUserId());
        AppUserWallet appUserWalletOld = walletMapper.selectById(payDetail.getUserId());
        // 加钱
        userMapper.logForAddGoldBalance(
            PayLogDTO.builder()
                .traceId(payDetail.getId())
                .uid(payDetail.getUserId())
                .changeNum(payDetail.getGold())
                .serviceTag("用户充值金币:" + payDetail.getOrderId())
                .logType(PayLogTypeEnums.收益_充值金币)
                .build());
        // 累计充值
        userMapper.addGoldCount(payDetail.getUserId(), payDetail.getGold(), 1);
        AppUserWallet appUserWalletNew = walletMapper.selectById(payDetail.getUserId());

        // 更新支付订单
        payDetail.setBeforeGoldBalance(appUserWalletOld.getGoldBalance());
        payDetail.setAfterGoldBalance(appUserWalletNew.getGoldBalance());
        payDetail.setGold(payDetail.getGold());
        payDetail.setThirdId(System.currentTimeMillis() + "" + Math.floor(Math.random() * 9000 + 1000));
        payDetail.setStatus(PayStatusEnum.已支付.getCode());
        baseMapper.updateById(payDetail);

        PushMessage.sendSysNotify(
            user.getPlatformId(),
            "恭喜您，充值成功!您充值的" + payDetail.getGold() + "个金币，已到账，请前往我的钱包查看!");

        // 跑马灯推送
        SpringUtil.publishEvent(
            PushRollingEvent.builder()
                .type(PushRollingEvent.Type.充值.getCode())
                .nickName(appUserExt.getNickName())
                .headUrl(appUserExt.getHeadUrl())
                .content(JSONUtil.createObj().set("num", payDetail.getGold()))
                .build());

        // 充值奖励
        if(!Objects.isNull(user.getPid()) && user.getPid() > 0){
            Long count = baseMapper.selectCount(
                Wrappers.lambdaQuery(PayDetail.class)
                    .eq(PayDetail::getUserId, payDetail.getUserId())
                    .eq(PayDetail::getStatus, PayStatusEnum.已支付.getCode()));
            //应用邀请奖励
            if(count <= 1){
                rewardService.inviteRewardFirst(payDetail.getId(), payDetail.getGold(), user.getPid());
            }
            rewardService.inviteRewardRecharge(payDetail.getId(), payDetail.getGold(), user.getPid());
        }
    }

    /**
     * 修改充值明细
     */
    @Override
    public Boolean updateByBo(PayDetailBo bo) {
        PayDetail update = BeanUtil.toBean(bo, PayDetail.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PayDetail entity) {
        // TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除充值明细
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public TableDataInfo<StatisticsVo> queryStatistics(StatisticsBo bo, PageQuery pageQuery) {
        Page<StatisticsVo> result = baseMapper.queryStatistics(
            bo.getDate(),
            bo.getBranch(),
            bo.getIsInvite(),
            pageQuery.build());
        return TableDataInfo.build(result);
    }

    private final IBrokerUserService sysUserService;
    @Override
    public TableDataInfo<StatisticsVo> queryInviteStatistics(StatisticsBo bo, PageQuery pageQuery) {
        Page<StatisticsVo> result = baseMapper.queryInviteStatistics(
            bo.getDate(),
            sysUserService.selectUserById(LoginHelper.getUserId()).getBranch(),
            pageQuery.build());
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<MonthStatisticsVo> queryMonthStatistics(MonthStatisticsBo bo, PageQuery pageQuery) {
        Page<MonthStatisticsVo> result = baseMapper.queryMonthStatistics(
            bo.getStartDate(),
            bo.getEndDate(),
            bo.getBranch(),
            bo.getIsInvite(),
            pageQuery.build());
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<InviteInfoVo> queryInviteInfo(InviteInfoBo bo, PageQuery pageQuery) {
        Page<InviteInfoVo> result = baseMapper.queryInviteInfo(
            bo.getDate(),
            sysUserService.selectUserById(LoginHelper.getUserId()).getBranch(),
            bo.getSex(),
            bo.getPlatformId(),
            pageQuery.build());
        return TableDataInfo.build(result);
    }
}
